const GoodsModel = require("../model/GoodsModel");
const CategoryModel = require("../model/CategoryModel");
const SupplierModel = require("../model/SupplierModel");
const { getChineseAcronym } = require("../utils/utils.js");

// 引入日志服务、日志类型
const logService = require("../utils/logService.js");
const LOG_TYPES = require("../constants/logTypes.js");

// 正则表达式
const CODE_PREFIX = "FD";
const GOODS_NAME_REGEX = /^[\u4e00-\u9fa5a-zA-Z0-9\s()（）-]{2,100}$/;
// 食材名称正则：必须由汉字、字母、数字、空格和特定标点符号（括号、破折号）组成，且长度在 2 到 100 个字符之间

class GoodsController {
  constructor() {
    this.goodsModel = new GoodsModel();
    this.categoryModel = new CategoryModel();
    this.supplierModel = new SupplierModel();
    this.categoryMap = null;
  }

  async _ensureCategoryMapLoaded() {
    if (!this.categoryMap) {
      const categories = await this.categoryModel.getCategoryList();
      this.categoryMap = categories.reduce((map, item) => {
        const acronym = getChineseAcronym(item.name);
        map[item.cate_id] = {
          name: item.name,
          acronym: acronym,
        };
        return map;
      }, {});
    }
  }
  // 校验新增、更新的数据
  async _validateGoodsData(data, isUpdate = false) {
    const errors = {};

    if (!isUpdate || data.name !== undefined) {
      if (!data.name) errors.name = "食材名称不能为空";
      else if (!GOODS_NAME_REGEX.test(data.name))
        errors.name = "食材名称格式不正确";
    }

    if (data.code !== undefined || data.goods_id !== undefined) {
      errors.system_field = "食材编号和ID应由系统管理，不允许手动提供或修改";
    }

    if (!isUpdate || data.cate_id !== undefined) {
      if (!data.cate_id) errors.cate_id = "分类ID不能为空";

      const cateId = parseInt(data.cate_id);
      if (isNaN(cateId)) {
        errors.cate_id = "分类ID必须是数字";
      } else {
        data.cate_id = cateId;
        await this._ensureCategoryMapLoaded();
        if (!this.categoryMap[data.cate_id])
          errors.cate_id = "提供的分类ID不存在";
      }
    }
    // 单位校验
    if (!isUpdate || data.unit !== undefined) {
      if (
        !data.unit ||
        (typeof data.unit === "string" && data.unit.trim() === "")
      )
        errors.unit = "单位不能为空";
    }

    if (data.specification !== undefined) {
      data.specification =
        typeof data.specification === "string"
          ? data.specification.trim()
          : null;
      if (data.specification === "") data.specification = null;
    } else {
      if (!isUpdate) data.specification = null;
    }
    // 规范化 supplier_id
    if (data.supplier_id !== undefined && data.supplier_id !== null) {
      const supplierId = parseInt(data.supplier_id);
      if (isNaN(supplierId) || supplierId < 0) {
        errors.supplier_id = "默认供应商ID无效";
      } else {
        data.supplier_id = supplierId;
      }
    } else {
      if (!isUpdate) data.supplier_id = null;
    }
    // 状态校验
    if (data.status !== undefined) {
      data.status = parseInt(data.status);
      if (![0, 1].includes(data.status)) {
        errors.status = "状态值无效，必须为 1 (启用) 或 0 (停用)";
      }
    }
    const priceFields = ["in_price", "out_price"];
    const stockFields = ["safety_stock"];
    const allFields = [...priceFields, ...stockFields];

    allFields.forEach((field) => {
      if (data[field] !== undefined) {
        const numValue = parseFloat(data[field]);

        if (isNaN(numValue) || numValue < 0) {
          const name =
            field === "safety_stock"
              ? "安全库存"
              : field === "in_price"
              ? "入库单价"
              : "出库单价";
          errors[field] = `${name}必须是大于等于零的数字`;
        } else {
          if (priceFields.includes(field)) {
            data[field] = parseFloat(numValue.toFixed(2));
          } else if (stockFields.includes(field)) {
            data[field] = parseFloat(numValue.toFixed(1));
          }
        }
      } else if (!isUpdate) {
        data[field] = 0.0;
      }
    });

    if (data.note !== undefined) {
      data.note = typeof data.note === "string" ? data.note.trim() : null;
      if (data.note === "") data.note = null;
    } else if (!isUpdate) {
      data.note = null;
    }

    return errors;
  }
  // 获取食材列表 (GET /goods)
  async getGoodsList(req, res) {
    const { page, pageSize, keyword, status, cateId, supplierId } = req.query;

    try {
      const result = await this.goodsModel.getAllGoods({
        page: parseInt(page) || 1,
        pageSize: parseInt(pageSize) || 10,
        keyword,
        status: status !== undefined ? parseInt(status) : 1,
        cateId: cateId ? parseInt(cateId) : null,
        supplierId: supplierId ? parseInt(supplierId) : null,
      });

      return res.status(200).json({
        code: 0,
        msg: "success",
        data: result,
      });
    } catch (err) {
      console.error(err.message);
      return res.status(500).json({ code: 1, msg: "获取食材列表失败。" });
    }
  }
  // 获取单个食材详情 (GET /goods/:id)
  async getGoodsDetail(req, res) {
    const goodsId = parseInt(req.params.id);
    if (isNaN(goodsId)) {
      return res.status(400).json({ code: 1, msg: "食材ID无效。" });
    }

    try {
      const data = await this.goodsModel.getGoodsById(goodsId);

      if (!data) {
        return res.status(404).json({ code: 1, msg: "食材不存在。" });
      }

      return res.status(200).json({ code: 0, msg: "success", data });
    } catch (err) {
      console.error(err.message);
      return res.status(500).json({ code: 1, msg: "获取食材详情失败。" });
    }
  }
  // 新增食材 (POST /goods)
  async createGoods(req, res) {
    const data = req.body;
    // 数据格式和必填字段校验
    const validationErrors = await this._validateGoodsData(data, false);
    if (Object.keys(validationErrors).length > 0) {
      return res
        .status(400)
        .json({ code: 1, msg: Object.values(validationErrors)[0] });
    }
    // 检查 复合唯一键 是否已存在
    try {
      const isDuplicate = await this.goodsModel.isCompositeKeyExist(
        data.name,
        data.specification,
        data.supplier_id,
        data.in_price
      );

      if (isDuplicate) {
        return res.status(400).json({
          code: 1,
          msg: "食材已添加。同名称、同规格、同供应商、同入库单价的食材不可重复添加。",
        });
      }
    } catch (err) {
      console.error(err.message);
      return res.status(500).json({ code: 1, msg: "复合唯一性检查失败。" });
    }
    // Code 自动生成
    try {
      await this._ensureCategoryMapLoaded();
      const categoryAcronym = this.categoryMap[data.cate_id].acronym;

      const { insertId, finalCode } =
        await this.goodsModel.addGoodsWithCodeTransaction(
          data,
          categoryAcronym
        );

      const op_type_num = LOG_TYPES.ADD_INGREDIENT;

      const op_desc = logService.formatLog(op_type_num, {
        name: data.name,
        goods_id: insertId,
        code: finalCode,
        spec: data.specification || "无规格",
      });

      logService.addLog(req, {
        op_type: op_type_num,
        op_desc,
      });
      return res.status(201).json({
        code: 0,
        msg: "新增食材成功，编号为 " + finalCode,
        data: { goods_id: insertId, code: finalCode },
      });
    } catch (err) {
      console.error(err.message);
      if (err.message.includes("已存在") || err.message.includes("事务回滚")) {
        return res.status(400).json({ code: 1, msg: err.message });
      }
      return res.status(500).json({ code: 1, msg: "新增食材失败。" });
    }
  }
  // 更新食材信息 (PUT /goods/:id)
  async updateGoods(req, res) {
    const goodsId = parseInt(req.params.id);
    const data = req.body;

    if (isNaN(goodsId) || Object.keys(data).length === 0) {
      return res
        .status(400)
        .json({ code: 1, msg: "ID无效或没有提供更新数据。" });
    }
    // 数据格式和必填字段校验
    const validationErrors = await this._validateGoodsData(data, true);
    if (Object.keys(validationErrors).length > 0) {
      return res
        .status(400)
        .json({ code: 1, msg: Object.values(validationErrors)[0] });
    }
    // 强制移除code、goods_id
    if (data.code !== undefined) delete data.code;
    if (data.goods_id !== undefined) delete data.goods_id;

    const currentGoods = await this.goodsModel.getGoodsById(goodsId);
    if (!currentGoods) {
      return res.status(404).json({ code: 1, msg: "食材不存在。" });
    }

    currentGoods.in_price = parseFloat(currentGoods.in_price);
    currentGoods.specification = currentGoods.specification || null;

    if (
      data.name !== undefined ||
      data.specification !== undefined ||
      data.supplier_id !== undefined ||
      data.in_price !== undefined
    ) {
      const newName = data.name !== undefined ? data.name : currentGoods.name;
      const newSpec =
        data.specification !== undefined
          ? data.specification
          : currentGoods.specification;
      const newSupplierId =
        data.supplier_id !== undefined
          ? data.supplier_id
          : currentGoods.supplier_id;
      const inPriceValue =
        data.in_price !== undefined ? data.in_price : currentGoods.in_price;
      const newInPrice = parseFloat(Number(inPriceValue).toFixed(2));

      try {
        const inPriceString = newInPrice.toFixed(2);
        const isDuplicate = await this.goodsModel.isCompositeKeyExist(
          newName,
          newSpec,
          newSupplierId,
          inPriceString,
          goodsId
        );

        if (isDuplicate) {
          return res.status(400).json({
            code: 1,
            msg: "更新后的食材组合已存在。同名称、同规格、同供应商、同入库单价的食材不可重复。",
          });
        }
      } catch (err) {
        console.error(err.message);
        return res.status(500).json({ code: 1, msg: "复合唯一性检查失败。" });
      }
    }
    // Code重生成
    if (data.cate_id !== undefined && currentGoods.cate_id !== data.cate_id) {
      // 只有在 cate_id 实际发生变化时才执行 Code 重生成
      await this._ensureCategoryMapLoaded();
      const cateAcronym = this.categoryMap[data.cate_id].acronym;

      const idString = String(goodsId).padStart(3, "0");
      const newCode = `${CODE_PREFIX}${cateAcronym}${idString}`;

      data.code = newCode;
    } else if (
      data.cate_id !== undefined &&
      currentGoods.cate_id === data.cate_id
    ) {
      delete data.cate_id;
    }
    try {
      const affectedRows = await this.goodsModel.updateGoods(goodsId, data);

      if (affectedRows === 0) {
        // 检查是否存在，如果不存在则 404
        const existingGoods = await this.goodsModel.getGoodsById(goodsId);
        if (!existingGoods) {
          return res.status(404).json({ code: 1, msg: "食材不存在。" });
        }
        return res.status(200).json({ code: 0, msg: "数据没有改变。" });
      }

      if (data.status !== undefined && data.status !== currentGoods.status) {
        const isEnabling = data.status === 1;
        const op_type_num = isEnabling
          ? LOG_TYPES.ENABLE_INGREDIENT
          : LOG_TYPES.DISABLE_INGREDIENT;
        const op_desc = logService.formatLog(op_type_num, {
          name: currentGoods.name,
          goods_id: goodsId,
          code: currentGoods.code,
          spec: currentGoods.specification || "无规格",
        });

        logService.addLog(req, {
          op_type: op_type_num,
          op_desc,
        });
      }

      const updateMsg = data.code ? `，编号已更新为: ${data.code}` : "";
      return res
        .status(200)
        .json({ code: 0, msg: `食材信息更新成功${updateMsg}` });
    } catch (err) {
      console.error(err.message);
      if (err.message.includes("已存在")) {
        return res.status(400).json({ code: 1, msg: err.message });
      }
      return res.status(500).json({ code: 1, msg: "更新食材信息失败。" });
    }
  }
  // 停用食材 (DELETE /goods/:id 软删除)
  async deactivateGoods(req, res) {
    const goodsId = parseInt(req.params.id);

    if (isNaN(goodsId)) {
      return res.status(400).json({ code: 1, msg: "食材ID无效。" });
    }

    const currentGoods = await this.goodsModel.getGoodsById(goodsId);
    if (!currentGoods) {
      return res.status(404).json({ code: 1, msg: "食材不存在。" });
    }
    if (currentGoods.status === 0) {
      return res.status(200).json({ code: 0, msg: "食材已处于停用状态。" });
    }

    try {
      const success = await this.goodsModel.deactivateGoods(goodsId);

      if (success) {
        const op_type_num = LOG_TYPES.DISABLE_INGREDIENT;

        const op_desc = logService.formatLog(op_type_num, {
          name: currentGoods.name,
          goods_id: goodsId,
          code: currentGoods.code,
          spec: currentGoods.specification || "无规格",
        });

        logService.addLog(req, {
          op_type: op_type_num,
          op_desc,
        });

        return res.status(200).json({ code: 0, msg: "食材已成功停用。" });
      } else {
        return res.status(404).json({ code: 1, msg: "食材不存在或无法停用。" });
      }
    } catch (err) {
      console.error(err.message);
      return res.status(500).json({ code: 1, msg: "食材停用操作失败。" });
    }
  }
  // 获取分类列表 GET /goods/categories
  async getGoodsCategories(req, res) {
    try {
      const list = await this.categoryModel.getCategoryList();
      const formattedList = list.map((item) => ({
        id: item.cate_id,
        name: item.name,
        order: item.cate_order,
      }));
      return res.status(200).json({
        code: 0,
        msg: "success",
        data: formattedList,
      });
    } catch (err) {
      console.error(err.message);
      return res.status(500).json({ code: 1, msg: "获取商品分类失败。" });
    }
  }
  // 获取供应商列表 GET /goods/suppliers
  async getGoodsSuppliers(req, res) {
    try {
      const result = await this.supplierModel.getAllSuppliers({
        page: 1,
        pageSize: 9999,
        status: "active",
        keyword: "",
        rating: null,
        cate_ids: null,
      });
      const formattedList = result.data.map((item) => ({
        id: item.supplier_id,
        name: item.supplier_name,
        status: item.status,
        rating_level: item.rating_level,
        notes: item.notes,
      }));

      return res.status(200).json({
        code: 0,
        msg: "success",
        data: formattedList,
      });
    } catch (err) {
      console.error(err.message);
      return res.status(500).json({ code: 1, msg: "获取供应商列表失败。" });
    }
  }
}

module.exports = GoodsController;
